//
// Created by shen on 2024/12/18.
//

#include "VideoDecoder.h"

VideoDecoder::VideoDecoder(FFStatus *status, JavaCallHelper *helper) : status(status),helper(helper) {
    this->helper=helper;
    this->status=status;
    queue=new SafeQueue(status);
    frameQueue = new AVFrameQueue(status);
    pthread_mutex_init(&codecMutex,NULL);
}


void VideoDecoder::setIsFramePreview(bool isFramePreview) {
    if (status){
        status->isFramePreview = isFramePreview;
    }
}
long startTime;
struct timeval tv;
void videplay(VideoDecoder *videoDecoder){

    while(videoDecoder->status!= nullptr
          &&!videoDecoder->status->exit){

        //首次进入 需要记录当前的时间
        if (videoDecoder->frameQueue->getQueueSize() == 0){
            gettimeofday(&tv,NULL);
            startTime = tv.tv_sec*1000 + tv.tv_usec/1000;
        }


        if (videoDecoder->status->isPause){
            av_usleep(1000 * 100);
            continue;
        }

        if (videoDecoder->status->isInited){
            videoDecoder->status->isInited = true;
            if (videoDecoder->queue->getQueueSize() == 0){
                if (!videoDecoder->status->loading){
                    videoDecoder->status->loading = true;
                    LOGE("loading");
//                    videoDecoder->helper->onLoad(true,THREAD_CHILD);
                }
                av_usleep(1000 * 20);
                continue;
            }else{
                if (videoDecoder->status->loading){
                    videoDecoder->status->loading = false;
                    LOGE("loading not first");
                }
            }
        }

        if (videoDecoder->status->isFramePreview){
            int queueSize=0;
            queueSize = videoDecoder->frameQueue->getQueueSize();
            if (queueSize >= videoDecoder->cacheFrameNum){
                av_usleep(1000*10);
                continue;
            }
        }

        if(videoDecoder->status->isSeekPause && videoDecoder->status->isBackSeekFramePreview){
            av_usleep(1000*1);
            continue;
        }


        AVPacket *avPacket = av_packet_alloc();
        if (!videoDecoder->status->isFramePreview && videoDecoder->frameQueue->getQueueSize() > 0){

        } else{
            if (videoDecoder->queue->getAvPacket(avPacket) != 0){
                av_packet_free(&avPacket);
                av_free(avPacket);
                avPacket = NULL;
                continue;
            }
        }
//        if (!videoDecoder->status->isFramePreview && videoDecoder->status->getQueueSize() > 0){



//        }

        pthread_mutex_lock(&videoDecoder->codecMutex);
        if (!videoDecoder->status->isFramePreview&&videoDecoder->frameQueue->getQueueSize() > 0){

        }else{
            if (avcodec_send_packet(videoDecoder->avCodecContext,avPacket)!=0){
                av_packet_free(&avPacket);
                av_free(avPacket);
                avPacket = NULL;
                pthread_mutex_unlock(&videoDecoder->codecMutex);
                continue;
            }
        }

        auto *avFrame=av_frame_alloc();
        /**
         * 不是预览模式且有缓存
         */
        if (!videoDecoder->status->isFramePreview&&
                videoDecoder->frameQueue->getQueueSize() > 0){
            videoDecoder->frameQueue->getAvFrame(avFrame);
        }else{
            //从avCodec直接解码
            if(avcodec_receive_frame(videoDecoder->avCodecContext,avFrame) != 0){
                av_frame_free(&avFrame);
                av_free(avFrame);
                avFrame = NULL;
                av_packet_free(&avPacket);
                av_free(avPacket);
                avPacket = NULL;
                pthread_mutex_unlock(&videoDecoder->codecMutex);
                continue;
            }
        }

        if (avFrame->format == AV_PIX_FMT_YUV420P
        || avFrame->format == AV_PIX_FMT_YUVJ420P){





        }


    }
}

void VideoDecoder::play() {
    if (status!= nullptr&&!status->exit){
        play_thread=std::thread(videplay,this);
    }
}

VideoDecoder::~VideoDecoder() {
    delete frameQueue;
    delete queue;
}
